﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;

public class TestAB : MonoBehaviour {

	public UIInput hostnameInput;

	public UIInput portInput;

	public UIInput threadInput;

	public UIInput webPathInput;

	public UILabel tipLabel;

	public GameObject testPanel;

	public UILabel threadLable;

	public UILabel connectLable;

	public UILabel closedLabel;

	public static TestAB Instance;

	public static string hostname;

	public static int port;

	public static int threadSize;

	public static string webPath;

	public static int threaded;

	public static int connected;

	public static int closed;

	public static void www(string url, object post, CallBackData<string> callBack){
		MeContext.addCastEnumerator(()=>{return wwwEnumerator(url, post, callBack);});
	}

	public static IEnumerator wwwEnumerator(string url, object post, CallBackData<string> callBack){
		url = "http://" + hostname + ":8080/" + webPath + "api/"+ url;
		byte[] postData = NetUtils.getPostData(post);
		if (postData == null) {
			postData = NetUtils.POST_DATA;
		}
		
		WWW www = new WWW (url, postData, NetUtils.header);
		//MeDialog.showDialog (dialogName);
		string data = "failed";
		try {
			yield return www;
			if (www.error == null) {
//				Dictionary<string, string> responseHeaders = www.responseHeaders;
//				if (responseHeaders.ContainsKey ("SET-COOKIE")) {
//					string cookie = www.responseHeaders ["SET-COOKIE"];
//					if (cookie != null) {
//						header.Remove ("COOKIE");
//						header.Add ("COOKIE", cookie);
//					}
//				}
				//data
				if (SocketAdapter.Debug) {
					data = www.text;
					
				} else {
					data = NetUtils.getReceiveValue<string> (www.bytes, 0);
				}
			}
			
		} finally {
			//MeDialog.closeDialog (dialogName);
			callBack (data);
		}
	}
	
	public static void www(SocketAdapter adapter, string url, CallBackData<string> callBack){
		adapter.send(Encoding.UTF8.GetBytes("api/" + url), null, 10000, null, (pos, buffers)=>{
			string data = pos < 0 ? "failed" : NetUtils.getReceiveValue<string>(buffers, pos);
			if(callBack!=null){
				callBack(data);
			}
		});
	}

	void Awake() {
		/*
		string name = "dadsdacxcxc";
		Debug.Log("name = " + name);
		byte[] data = Encoding.UTF8.GetBytes(name);
		MemoryStream stream = new MemoryStream();
		CommonUtils.zipCompress(data, 0, data.Length, stream);
		data = stream.GetBuffer();
		name = CommonUtils.zipDeCompressString(data);
		Debug.Log("name deCompress = " + name);
		*/
		//MeContext.addCastEnumerator(GameMonoUtils.getDelayEnumerator(1, ()=>{Debug.Log("GameMonoUtils.getDelayEnumerator");}));

		Instance = this;
		string value = PlayerPrefs.GetString("hostname");
		if(value == null || "".Equals(value)) {
			value = "192.168.1.21";
		}

		hostnameInput.value = value;

		value = PlayerPrefs.GetString("port");
		if(value == null || "".Equals(value)) {
			value = "18890";
		}
		
		portInput.value = value;

		value = PlayerPrefs.GetString("thread");
		if(value == null || "".Equals(value)) {
			value = "1024";
		}
		
		threadInput.value = value;

		value = PlayerPrefs.GetString("webPath");
		if(value == null || "".Equals(value)) {
			value = "achieve-dtyx/";
		}
		
		webPathInput.value = value;

		tipLabel.text = "ready test";

		SocketAdapter.Debug = false;
		//NetUtils.header.Add("identity", "apiRoute," + "123456");
	}

	public void Update() {
		threadLable.text = threaded.ToString();
		connectLable.text = connected.ToString();
		closedLabel.text = closed.ToString();
	}

	public void test() {
		hostname = hostnameInput.value;
		port = int.Parse(portInput.value);
		threadSize = int.Parse(threadInput.value);
		webPath = webPathInput.value;
		PlayerPrefs.SetString("hostname", hostname);
		PlayerPrefs.SetString("port", port.ToString());
		PlayerPrefs.SetString("thread", threadSize.ToString());
		PlayerPrefs.SetString("webPath", webPath);
		www ("entity/changed/JQuestionCategory", null, testRewardDefine);
	}

	protected static List<Thread> threads;

	public void stop() {
		if(testPanel.activeSelf) {
			tipLabel.text = "ready test";
			foreach(Thread thread in threads) {
				thread.Interrupt();
				thread.Abort();
			}

			threads = null;
			testPanel.SetActive(false);
		}
	}

	public void testRewardDefine(string data) {
		if("failed" == data) {
			tipLabel.text = "connect error!";
			
		} else {
			if(testPanel.activeSelf) {
				tipLabel.text = "test is started!";
				
			} else {
				tipLabel.text = "OK";
				testPanel.SetActive(true);
				threads = new List<Thread>(threadSize);
				StartCoroutine(testThreadStarts(threads));
			}
		}
	}

	public IEnumerator testThreadStarts(List<Thread> starts) {
		for(int i = 0; i < threadSize; i++) {
			testThreadStart("C_" + SystemInfo.deviceUniqueIdentifier + "_" + i, threads);
			yield return new WaitForSeconds(0.1f);
			if(threads != starts) {
				break;
			}
		}
	}

	// test Thread Start
	public void testThreadStart(string identity, List<Thread> starts) {
		//string nameUrl = "user/play?identity=" + identity;
		www("player?identity="+ identity, null, (playerContext)=>{
			//Debug.Log("login=>" + identity + " : " + playerContext);
			if("failed".Equals(playerContext)) {
				www("user/play?identity=" + identity, identity, (data)=>{
					//Debug.Log("play name=>" + identity + " : " + data);
					if("false".Equals(data)) {
						startTestThread(identity, starts);
						
					} else if("true".Equals(data)) {
						int cardId = Random.Range(1, 3);
						string cardurl = "user/play/" + cardId + "?identity=" + identity;
						www(cardurl, null, (register)=>{
							//Debug.Log("play cardId=>" + identity + " : " + register);
							if("failed".Equals(register)) {
								//Debug.Log("select card " + cardId + " failed = " + identity);
								
							} else {
								startTestThread(identity, starts);
							}
						});
					} 
				});

			} else {
				startTestThread(identity, starts);
			}
		});
	}

	public void startTestThread(string identity, List<Thread> starts) {
		if(starts == threads) {
			//Debug.Log("startTestThread =>" + identity + " : " + new System.Exception());
			Thread thread = new Thread(createThreadStart(identity, starts));
			starts.Add(thread);
			thread.Start();
		}
	}

	public static ThreadStart createThreadStart(string identity, List<Thread> starts) {
		return ()=> {
			new TestBot(starts).start(identity);
		};
	}

	public class SocketAdapterTest : SocketAdapter {

		private object starts;

		public SocketAdapterTest(object starts) {
			this.starts = starts;
		}

		public override bool step (int contextTick) {
			if(starts != threads) {
				return false;
			}

			return base.step(contextTick);
		}
	}
	
	public class TestBot {

		private SocketAdapter adapter;

		public TestBot(List<Thread> starts) {
			adapter = new SocketAdapterTest(starts);
		}

		public void start(string identity) {
			threaded++;
			adapter.connectOpen = ()=>{
				IPAddress address = IPAddress.Parse(hostname);
				IPEndPoint endPoint = new IPEndPoint(address, port);
				Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
				try {
					socket.BeginConnect(endPoint, (ar) => {
						adapter.connectSend(socket, Encoding.UTF8.GetBytes("apiRoute," + identity), null);
						//socket.BeginSend(loginBytes, 0, loginBytes.Length, SocketFlags.None, null, null);
					}, null);

					return socket;
					
				} catch(System.Exception e) {
					Debug.Log("connectOpen:");
				}
				
				return null;
			};

			adapter.connectClose = ()=> {
				Debug.Log("connectClose:");
				closed++;
				return true;
			};

			adapter.connectLogin = (data) => {
				// + new System.Exception()
				Debug.Log("connectLogin:" + data);
				bool logined = "ok".Equals(data);
				if(logined){
					connected++;
				}

				return logined;
			};

			adapter.connectCallBacks=(pos, data)=>{	
			};

			/*/*
			www(adapter, "api/social/favorite23223s", (data)=>{
				Debug.Log("testResponse:" + data);
			});

			return;
			//*/

			while(true) {
				if(stepUrl == null) {
					stepUrl = "player/task/0/0/0";
				}

				www(adapter, stepUrl, stepComplete);
				stepUrl = null;
				stepInterval = 30;
				while(--stepInterval > 0) {
					try {
						Thread.Sleep(10000);

					} catch(System.Exception e) {
						break;
					}
				}

				try {
					Thread.Sleep(10000);
					
				} catch(System.Exception e) {
					break;
				}
			}

			threaded--;
		}

		private string stepUrl;

		private int stepInterval;

		private int stepIndex;

		protected void stepComplete(string data) {
			//Debug.Log("stepComplete" + data);
			if("failed".Equals(data)) {
				stepIndex = 0;

			} else {
				switch(stepIndex++) {
				case 0:
					stepUrl = "fight/question/" + Random.Range(0, 3);
					break;

				case 1:
					stepUrl = "fight/answer/" + Random.Range(0, 3);
					break;

				default:
					stepIndex = 0;
					break;
				}
			}

			stepInterval = 0;
		}
	}



























	/*** end complete ***/
}
